package de.iritgo.skillfull.component.visual;

import java.awt.Dimension;

import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.SpriteSheet;

import de.iritgo.skillfull.component.VisualComponentImpl;
import de.iritgo.skillfull.component.visitor.PositionVisitor;
import de.iritgo.skillfull.component.visitor.Visitor;
import de.iritgo.skillfull.entity.Entity;

public class SpriteSheetRenderComponentImpl extends VisualComponentImpl implements SpriteSheetRenderComponent 
{	
	
	private String imageFilename;

	private SpriteSheet spriteSheet;
	
	private Image currentImage;

	private int tileWidth;

	private int tileHeight;
	
	private boolean autoUpdate;
	
	private int tilesX;
	
	private int tilesY;

	private int spriteSheetX;
	
	private int spriteSheetY;
	
	private int time;

	private float nextTick;
	
	private int duration;
	
	private float speed;

	private Integer[] framesX;

	private Integer[] framesY;

	private int centerX;

	private int centerY;
	
	private boolean played;

	private int spriteframeCount;

	private boolean loop;

	private boolean continuous;

	private float rx;

	private float ry;

	private float rwidth;

	private float rheight;
	
	public String getImageFilename ()
	{
		return imageFilename;
	}

	public void setImageFilename (String imageFilename)
	{
		this.imageFilename = imageFilename;
	}

	public void setTileWidth(int tileWidth) 
	{
		this.tileWidth = tileWidth;
	}

	public void setTileHeight(int tileHeight) 
	{
		this.tileHeight = tileHeight;
	}

	public void setAutoUpdate(boolean autoUpdate) 
	{
		this.autoUpdate = autoUpdate;
	}

	public void setTilesX(int tilesX) 
	{
		this.tilesX = tilesX;
	}

	public void setTilesY(int tilesY) 
	{
		this.tilesY = tilesY;
	}
	
	public void setDuration(int duration) 
	{
		this.duration = duration;
	}

	public void setSpeed (float speed) 
	{
		this.speed = speed;
	}

	public void setFramesX (Integer[] framesX)
	{
		this.framesX = framesX;
	}
	
	public void setFramesY (Integer[] framesY)
	{
		this.framesY = framesY;
	}

	public void setCenterX (int centerX)
	{
		this.centerX = centerX;
	}
	
	public void setCenterY (int centerY)
	{
		this.centerY = centerY;
	}

	public void setRx(float rx) 
	{
		this.rx = rx;
	}

	public void setRy(float ry) 
	{
		this.ry = ry;
	}

	public void setRwidth(float rwidth) 
	{
		this.rwidth = rwidth;
	}

	public void setRheight(float rheight) 
	{
		this.rheight = rheight;
	}

	public void initialize ()
	{
		if (imageFilename == null)
			return;

		try
		{
			spriteSheet = new SpriteSheet (imageFilename, tileWidth, tileHeight);
			currentImage = spriteSheet.getSubImage (0,0);
			if (centerX == 0 && centerY == 0)
			{
				currentImage.setCenterOfRotation (currentImage.getWidth() / 2.0f * scale, currentImage.getHeight() / 2.0f * scale);
			}
			else
			{
				currentImage.setCenterOfRotation (centerX, centerY);
			}
			rx = ry = 0;
			rwidth = tileWidth;
			rheight = tileHeight;
		}
		catch (SlickException e)
		{
			e.printStackTrace();
		}
	}
	
	public void init ()
	{
		x = -32;
		y = -32;
	}
	
	public void printConfiguration ()
	{
		System.out.println ("     " + toString ());
		System.out.println ("      Scale: " + scale);
	}

	public void accept (Visitor visitor)
	{
		visitor.visit (this);
	}
	
	public void setScale (float scale)
	{
		this.scale = scale;
	}

	public void startAnimation(boolean autoUpdate, boolean loop, boolean continuous) 
	{
		this.autoUpdate = autoUpdate;
		active = true;
		played = false;
		this.continuous = continuous;
		if (! continuous)
		{
			spriteframeCount = 0;
		}
		this.loop = loop;
	}
	
	public void stopAnimation() 
	{
		active = false;
		autoUpdate = false;
		played = true;
		loop = false;
	}
	
	public void update (GameContainer container, int delta, Entity entity)
	{
		nextTick -= delta;
		
		while (nextTick < 0)
		{
			nextTick += duration / speed;
			if (autoUpdate && active)
			{
				++spriteSheetX;
				if (spriteSheetX >= tilesX)
				{
					spriteSheetX = 0;
					++spriteSheetY;
				}
				if (spriteSheetY >= tilesY)
				{
					played = true;
					spriteSheetX = 0;
					spriteSheetY = 0;
				}
				currentImage = spriteSheet.getSubImage (spriteSheetX, spriteSheetY);
			}
			else if (active)
			{
				if (spriteframeCount < framesX.length || spriteframeCount < framesY.length)
				{
					currentImage = spriteSheet.getSubImage (framesX[spriteframeCount], framesY[spriteframeCount]);
					++spriteframeCount;
				}
				else
				{
					if (loop || continuous)
					{
						spriteframeCount = 0;
					}
					else
					{
						played = true;
					}
				}
			}
		}
	}

		public boolean isPlayed() 
		{
			return played;
		}
	/**
	 * @see de.iritgo.skillfull.component.VisualComponentImpl#render(org.newdawn.slick.GameContainer, org.newdawn.slick.Graphics, de.iritgo.skillfull.entity.Entity)
	 */
	public void render (GameContainer container, Graphics g, Entity entity)
	{
		currentImage.setRotation (rotation);
		currentImage.draw(x, y, rwidth, rheight);
//		currentImage.draw (x, y, scale);
	}

	public Dimension getDimension ()
	{
		return new Dimension (currentImage.getWidth (), currentImage.getHeight ());
	}
}	
	

